package design.mode.chapter3.item3.versionPlus.controller;


import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import design.mode.chapter3.item3.versionPlus.Stroage.MetricsStorage;
import design.mode.chapter3.item3.versionPlus.Stroage.RedisMetricsStorage;
import design.mode.chapter3.item3.versionPlus.domain.RequestInfo;
import java.util.concurrent.Executors;

/**
 * 类负责提供 API，来采集接口请求的原始数据
 * 我们通过在 MetricsCollector 中引入 Google Guava EventBus 来解决。
 * 实际上，我们可以把 EventBus 看作一个“生产者 - 消费者”模型或者“发布 - 订阅”模型，采集的数据先放入内存共享队列中，
 * 另一个线程读取共享队列中的数据，写入到外部存储（比如 Redis）中
 */
public class MetricsCollector {
    private EventBus eventBus;
    private MetricsStorage metricsStorage; // 基于接口编程而非实现编程

    // 兼顾代码的易用性，新增一个封装了默认依赖的构造函数
    public MetricsCollector() {
        this(new RedisMetricsStorage());
    }

    // 兼顾灵活性和代码的可测试性，这个构造函数继续保留
    // 依赖注入
    public MetricsCollector(MetricsStorage metricsStorage) {
        this.metricsStorage = metricsStorage;
    }

    public MetricsCollector(MetricsStorage metricsStorage, int threadNumToSaveData) {
        this.metricsStorage = metricsStorage;
        this.eventBus = new AsyncEventBus(Executors.newFixedThreadPool(threadNumToSaveData));
        this.eventBus.register(new EventListener());
    }

    // 用一个函数代替了最小原型中的两个函数
    public void recordRequest(RequestInfo requestInfo) {
        if (requestInfo == null || requestInfo.getApiName() == null || requestInfo.getApiName() == "") {
            return;
        }
        eventBus.post(requestInfo);
    }

    public class EventListener {
        @Subscribe
        public void saveRequestInfo(RequestInfo requestInfo) {
            metricsStorage.saveRequestInfo(requestInfo);
        }
    }
}
